home *** CD-ROM | disk | FTP | other *** search
- //============================================================================
- // control/players/weapon.cs
- //
- // Copyright (c) 2003 Kenneth C. Finney
- // Portions Copyright (c) 2001 GarageGames.Com
- // Portions Copyright (c) 2001 by Sierra Online, Inc.
- //============================================================================
-
- // This file contains Weapon and Ammo Class/"namespace" helper methods
- // as well as hooks into the inventory system. These functions are not
- // attached to a specific C++ class or datablock, but define a set of
- // methods which are part of dynamic namespaces "class". The Items
- // include these namespaces into their scope using the ItemData and
- // ItemImageData "className" variable.
-
- // All ShapeBase images are mounted into one of 8 slots on a shape.
- // This weapon system assumes all primary weapons are mounted into
- // this specified slot:
- $WeaponSlot = 0;
- //-----------------------------------------------------------------------------
- // Audio profiles
-
- datablock AudioProfile(WeaponUseSound)
- {
- filename = "~/data/sound/weapon_switch.wav";
- description = AudioClose3d;
- preload = true;
- };
-
- datablock AudioProfile(WeaponPickupSound)
- {
- filename = "~/data/sound/weapon_pickup.wav";
- description = AudioClose3d;
- preload = true;
- };
-
- datablock AudioProfile(AmmoPickupSound)
- {
- filename = "~/data/sound/ammo_pickup.wav";
- description = AudioClose3d;
- preload = true;
- };
- //-----------------------------------------------------------------------------
- // Weapon Class
- //-----------------------------------------------------------------------------
-
- function Weapon::onUse(%data,%obj)
- {
- // Default behavoir for all weapons is to mount it into the
- // this object's weapon slot, which is currently assumed
- // to be slot 0
- if (%obj.getMountedImage($WeaponSlot) != %data.image.getId())
- {
- %obj.mountImage(%data.image, $WeaponSlot);
- if (%obj.client)
- messageClient(%obj.client, 'MsgWeaponUsed', '\c0Weapon selected');
- }
- }
-
- function Weapon::onPickup(%this, %obj, %shape, %amount)
- {
- // The parent Item method performs the actual pickup.
- // For player's we automatically use the weapon if the
- // player does not already have one in hand.
- if (Parent::onPickup(%this, %obj, %shape, %amount))
- {
- if ( (%shape.getClassName() $= "Player" ||
- %shape.getClassName() $= "AIPlayer" ) &&
- %shape.getMountedImage($WeaponSlot) == 0)
- {
- %shape.use(%this);
- }
- }
- }
-
- function Weapon::onInventory(%this,%obj,%amount)
- {
- // Weapon inventory has changed, make sure there are no weapons
- // of this type mounted if there are none left in inventory.
- if (!%amount && (%slot = %obj.getMountSlot(%this.image)) != -1)
- %obj.unmountImage(%slot);
- }
-
-
- //-----------------------------------------------------------------------------
- // Weapon Image Class
- //-----------------------------------------------------------------------------
-
- function WeaponImage::onMount(%this,%obj,%slot)
- {
- // Images assume a false ammo state on load. We need to
- // set the state according to the current inventory.
- if (%obj.getInventory(%this.ammo))
- %obj.setImageAmmo(%slot,true);
- }
-
-
- //-----------------------------------------------------------------------------
- // Ammmo Class
- //-----------------------------------------------------------------------------
-
- function Ammo::onPickup(%this, %obj, %shape, %amount)
- {
- // The parent Item method performs the actual pickup.
- if (Parent::onPickup(%this, %obj, %shape, %amount))
- {
-
- }
- }
-
- function Ammo::onInventory(%this,%obj,%amount)
- {
- // The ammo inventory state has changed, we need to update any
- // mounted images using this ammo to reflect the new state.
- for (%i = 0; %i < 8; %i++)
- {
- if ((%image = %obj.getMountedImage(%i)) > 0)
- if (IsObject(%image.ammo) && %image.ammo.getId() == %this.getId())
- %obj.setImageAmmo(%i,%amount != 0);
- }
- }
-
- // Support function which applies damage to objects within the radius of
- // some effect, usually an explosion. This function will also optionally
- // apply an impulse to each object.
-
- function radiusDamage(%sourceObject, %position, %radius, %damage, %damageType, %impulse)
- {
- // Use the container system to iterate through all the objects
- // within our explosion radius. We'll apply damage to all ShapeBase
- // objects.
- InitContainerRadiusSearch(%position, %radius, $TypeMasks::ShapeBaseObjectType);
-
- %halfRadius = %radius / 2;
- while ((%targetObject = containerSearchNext()) != 0) {
-
- // Calculate how much exposure the current object has to
- // the explosive force. The object types listed are objects
- // that will block an explosion. If the object is totally blocked,
- // then no damage is applied.
- %coverage = calcExplosionCoverage(%position, %targetObject,
- $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType |
- $TypeMasks::ForceFieldObjectType | $TypeMasks::VehicleObjectType);
- if (%coverage == 0)
- continue;
-
- // Radius distance subtracts out the length of smallest bounding
- // box axis to return an appriximate distance to the edge of the
- // object's bounds, as opposed to the distance to it's center.
- %dist = containerSearchCurrRadiusDist();
-
- // Calculate a distance scale for the damage and the impulse.
- // Full damage is applied to anything less than half the radius away,
- // linear scale from there.
- %distScale = (%dist < %halfRadius)? 1.0:
- 1.0 - ((%dist - %halfRadius) / %halfRadius);
-
- // Apply the damage
- %targetObject.damage(%sourceObject, %position,
- %damage * %coverage * %distScale, %damageType);
-
- // Apply the impulse
- if (%impulse) {
- %impulseVec = VectorSub(%targetObject.getWorldBoxCenter(), %position);
- %impulseVec = VectorNormalize(%impulseVec);
- %impulseVec = VectorScale(%impulseVec, %impulse * %distScale);
- %targetObject.applyImpulse(%position, %impulseVec);
- }
- }
- }
-